import { createElement } from 'react';
import { LibResult, ResultMatch } from './Lib.interfaces';

function getMatches(result: LibResult, key: string, refIndex?: number) {
  return result.matches?.find((m) => m.key === key && refIndex === m.refIndex);
}

function getSlices(value: string, matches?: ResultMatch): Slice[] {
  if (!matches) {
    return [{ value, matched: false }];
  }

  const slices: Slice[] = [];
  const { indices } = matches;

  const [a0, b0] = indices[0];
  if (a0 > 0) {
    slices.push({ value: value.substring(0, a0), matched: false });
  }
  slices.push({ value: value.substring(a0, b0 + 1), matched: true });

  for (let i = 1; i < indices.length; i++) {
    const [, bP] = indices[i - 1];
    const [ai, bi] = indices[i];
    slices.push({ value: value.substring(bP + 1, ai), matched: false });
    slices.push({ value: value.substring(ai, bi + 1), matched: true });
  }

  const [, bE] = indices[indices.length - 1];
  if (bE < value.length - 1) {
    slices.push({
      value: value.substring(bE + 1, value.length),
      matched: false,
    });
  }

  return slices;
}

interface LibResultFieldProps {
  value: string;
  result: LibResult;
  matchKey: string;
  refIndex?: number;
}

export function LibResultField(props: LibResultFieldProps) {
  const { value, result, matchKey, refIndex } = props;
  const matches = getMatches(result, matchKey, refIndex);
  const slices = getSlices(value, matches);
  return (
    <>
      {slices.map((props, index) => (
        <SliceView key={index} {...props} />
      ))}
    </>
  );
}

interface Slice {
  value: string;
  matched?: boolean;
  type?: string;
}

function SliceView({ value = '', type = 'span', matched = false }: Slice) {
  return createElement(
    type,
    { className: matched ? 'matched' : undefined },
    value,
  );
}
